--[[
	自建桌子，里面就是最基本的打牌逻辑
]]
local filename = "table.lua"

local skynet = require "skynet"
local cluster = require "skynet.cluster"

local filelog = require "filelog"
local routerbase = require "routerbase"
require "mjexenum"

local json = require "cjson"
json.encode_sparse_array(true, 1, 1)

--
--构建一个桌子对象
--
local Table = routerbase:new({
	LOGICPOOL = {},
	table_data = {
		-- 来自原来的tableobj.lua
        table_type = 0,	            --桌子类型：1，自建房卡，2，自建钻石
		uuid = "",                  --唯一id
        tradeid = 0,                --节点唯一id
		index = 0,  	            --就是 table_index
        code = "",                  --桌号
		state = 0,	                --状态
		sitdown_player_num = 0,     --坐下的玩家数

        table_service = nil,        --桌子服务

        waits = {},                 --旁观队列 （等待列表）
        seats = {},                 --座位信息
        allrids = {}, 	            --  就是进入桌子的所有的rid，断线，离开的时候从这里去除，rid 是主键
						            --  进入的时候  allrids[rid] = 1,离开的时候 allrids[rid] = nil

		conf = nil,                 --桌子配置（来自客户端）
		gamelogic = nil,            --游戏逻辑对象
		timer_id = -1,              --通用计时器
		isdeleting = false,           --是否被标示为可删除
		cur_watch_playernum = 0,    --当前旁观人数

		--添加桌子的变量
		delete_table_timer_id = -1,     --删除倒计时
		disband_table_timer_id = -1,    --解散倒计时

		retain_to_time = 0,             --桌子保留到的时间(linux时间擢)
		retain_to_num = 0,              --游戏总共能进行的局数
		curr_to_num = 0,                --当前已经打了的局数

		one_start_time = 0,             --单局开局时间
        one_end_time = 0,               --单局结束时间
        start_time = 0,                 --游戏开始时间
		end_time = 0,                   --游戏结束时间

		action_timeout_time = 0,        --记录当前轮的操作到期时间,单位s
        do_select_timeout = 20,         --玩家选择操作的超时时间,单位s            测试20
        countdown_time = 3,             --一局游戏开始的倒计时，单位s            测试5
        do_tuoguan_time = 2,            --托管超时时间
        disband_timeout_time = 0,       --记录当前解散桌子的操作到期时间,单位s

		dice_one = 0,                   --骰子1点数
		dice_two = 0,                   --骰子2点数 
		
		action_player_list = nil,       --记录当前可以操作的玩家和其可以进行的操作
		--[[
			rid = {
				rid = 0,
				seat_index = 0,             当前操作玩家的座位号
                action_state = 0,       操作状态 0表示未操作 1表示接收操作未处理 2表示已处理
				action_type = 0,        记录玩家当前的操作类型
				wait_action_types = {       玩家可以执行的操作类型列表
					
				},         
			}
		]]

		chupai_count = 0,              --记录出牌次数

		--记录当前杠牌玩家 
		curr_gangpai_seat_index = 0,   --记录当前杠牌座位号
		curr_gangpai_info = nil,       --记录当前杠牌信息
		--[[
			{
				gang_seat_index =        引杠玩家座位号 自己座位号表示自己刚，否则就是别人引杠
				gang_peng_type =              杠碰类型 1 碰,2 直杠,3 巴杠（面下杠）4 暗杠	
				card =             牌值
			}
		]]
		
		chu_mo_paitag = 0,          --出摸牌类型， 0表示无, 1普通出牌, 2摸牌 3表示明杠(巴杠), 4表示杠出牌, 5表示请胡
		chu_mo_pai_seat_index = 0,  --出摸牌玩家座位号
		chu_mo_pai_card = 0,        --出摸牌的牌值

		curr_action_seat_index = 0, --记录当前操作玩家座位号，主要用于计算下一个触摸牌玩家

		--庄家位置
		banker_seat_index = 0,      --当前庄家位置		
		last_banker_seat_index = 0, --上一个庄家位置

		-- 一炮多响玩家位置
		ypdx_seat_index = 0,        --当前局一炮多响位置
		last_ypdx_seat_index = 0,   --上一局一炮多响位置

		--当前胡牌玩家位置
		hupai_seat_index = 0,       --当前局首先胡牌玩家位置
		last_hupai_seat_index = 0,  --上一局首先胡牌玩家位置

		is_will_delete = 0, 	    --在游戏中如果收到删除指令,则置1,游戏结束再处理
		backofconf = nil,           --缓存更新的配置文件

		cards_stack = nil,          --当前牌堆 
		game_records = nil,         --游戏战绩记录

		is_had_start = false,       --是否已经开局
        is_onegameend = false,       --是否一局结束

		playerdisbandlist = nil,        --解散玩家列表
		applydisband_seat_index = 0,    --申请解散的座位号
		apply_disband_time = 0,         --申请解散时间

		curr_actionplayer_rid = 0,      --当前操作玩家rid
		curr_actionplayer_cardcolor = 0,--记录当前操作牌花色
		curr_actionplayer_cards = nil,  --记录当前操作牌

        agencylevel = 0,            --代理等级，0表示非代理创建桌
        is_huansanzhang = false,    --是否换三张
        is_dingque = false,         --是否缺一门胡

        huansanzhang_list = nil,    --换三张列表
        que_color_list = nil,       --缺牌花色列表
        is_ingame = false,          --是否游戏中

	},
})


--
-- 初始化数据
--
-- 注意这里的顺序要先 add_logic ,然后再 add_func
-- 因为 func里的init 有会使用 logic 里的定义，所以要先add_loginc
--
function Table:init()
	-- 放到LOGICPOOL{} 里面执行了
	self:add_logic("tablelogic", "tablemsg/tablelogic")  -- 桌子逻辑
	self:add_logic("seatlogic", "tablemsg/seatlogic")    -- 座位逻辑	
	self:add_logic("gamelogic", "tablemsg/gamelogic")    -- 游戏逻辑

	-- 放到CMD{} 里面执行了
	self:add_func("tablemsg/tablecmd")
	self:add_func("tablemsg/tablerequest")
	self:add_func("tablemsg/tabletimer")
end

--
--添加逻辑处理模块
--
function Table:add_logic(name, logicfile)
	self.LOGICPOOL[name] = require(logicfile)
    if self.LOGICPOOL[name] then
	    if self.LOGICPOOL[name].init and type(self.LOGICPOOL[name].init) == "function" then
		    self.LOGICPOOL[name].init(self)
	    end
    else
        filelog.sys_error("add logic failed!",name,logicfile)
    end
end

--
--通过logic_name，获得逻辑对象
--
function Table:get_logicbyname(logic_name)
	return self.LOGICPOOL[logic_name]
end

--
--向列表中玩家发通知消息
--is_new_format 是否新格式
--
function Table:send_notice_to_players(rids, msgname, message, retcode, retstr, is_new_format)
    local status = false

    if is_new_format then
        local tmp = { msgname = msgname, msgbody = json.encode(message)}
        status = skynet.pcall(cluster.send,"gatenode", ".router", "notify", rids, "mjex.".. "notifyN", tmp, retcode, retstr)
    else
	    status = skynet.pcall(cluster.send,"gatenode", ".router", "notify", rids, "mjex."..msgname, message, retcode, retstr)
    end
    if not status then
        filelog.sys_error("notice player failed!")
    end
end

--
--  通知gate
--
function Table:notice_tableinfo_togatenode(msgname, rid, gamenode, table_index)
	local status = skynet.pcall(cluster.send,"gatenode", ".router", msgname, rid, gamenode, table_index)
    if not status then
        filelog.sys_error("send msg to gate error!")
    end
end

--
--  结束服务
--
function Table:exit_service()
	skynet.exit()
end

--
-- lua消息处理
--
function Table:process(command, ...)
	skynet.call(skynet.self(), "lua", command, ...)
end

skynet.start(function()
	Table:start()
end)